home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / Mesa-2.2 / src / varray.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-13  |  39.4 KB  |  1,305 lines

  1. /* $Id: varray.c,v 1.9 1997/01/30 21:05:03 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.2
  6.  * Copyright (C) 1995-1997  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: varray.c,v $
  26.  * Revision 1.9  1997/01/30 21:05:03  brianp
  27.  * moved gl_GetPointerv() to get.c
  28.  *
  29.  * Revision 1.8  1996/12/18 20:00:57  brianp
  30.  * gl_set_material() now takes a bitmask instead of face and pname
  31.  *
  32.  * Revision 1.7  1996/12/07 10:21:28  brianp
  33.  * call gl_set_material() instead of gl_Materialfv()
  34.  *
  35.  * Revision 1.6  1996/11/09 03:12:34  brianp
  36.  * now call gl_render_vb() after gl_transform_vb_part2() call
  37.  *
  38.  * Revision 1.5  1996/10/08 00:05:06  brianp
  39.  * added some missing stuff to gl_ArrayElement()
  40.  *
  41.  * Revision 1.4  1996/10/04 02:37:06  brianp
  42.  * gl_ArrayElement() wasn't always initializing vertex Z and W values
  43.  *
  44.  * Revision 1.3  1996/10/03 00:47:56  brianp
  45.  * added #include <stdlib.h> for abort()
  46.  *
  47.  * Revision 1.2  1996/09/27 01:33:07  brianp
  48.  * added missing default cases to switches
  49.  *
  50.  * Revision 1.1  1996/09/13 01:38:16  brianp
  51.  * Initial revision
  52.  *
  53.  */
  54.  
  55.  
  56.  
  57. /*
  58.  * NOTE:  At this time, only three vertex array configurations are optimized:
  59.  *  1.  glVertex3fv(), zero stride
  60.  *  2.  glNormal3fv() with glVertex3fv(), zero stride
  61.  *  3.  glNormal3fv() with glVertex4fv(), zero stride
  62.  *
  63.  * More optimized array configurations can be added.
  64.  */
  65.  
  66.  
  67.  
  68.  
  69. #include <stdlib.h>
  70. #include <string.h>
  71. #include "draw.h"
  72. #include "context.h"
  73. #include "enable.h"
  74. #include "dlist.h"
  75. #include "light.h"
  76. #include "macros.h"
  77. #include "types.h"
  78. #include "varray.h"
  79. #include "vb.h"
  80. #include "xform.h"
  81.  
  82.  
  83.  
  84. void gl_VertexPointer( GLcontext *ctx,
  85.                        GLint size, GLenum type, GLsizei stride,
  86.                        const GLvoid *ptr )
  87. {
  88.    if (size<2 || size>4) {
  89.       gl_error( ctx, GL_INVALID_VALUE, "glVertexPointer(size)" );
  90.       return;
  91.    }
  92.    if (stride<0) {
  93.       gl_error( ctx, GL_INVALID_VALUE, "glVertexPointer(stride)" );
  94.       return;
  95.    }
  96.    switch (type) {
  97.       case GL_SHORT:
  98.          ctx->Array.VertexStrideB = stride ? stride : size*sizeof(GLshort);
  99.          break;
  100.       case GL_INT:
  101.          ctx->Array.VertexStrideB = stride ? stride : size*sizeof(GLint);
  102.          break;
  103.       case GL_FLOAT:
  104.          ctx->Array.VertexStrideB = stride ? stride : size*sizeof(GLfloat);
  105.          break;
  106.       case GL_DOUBLE:
  107.          ctx->Array.VertexStrideB = stride ? stride : size*sizeof(GLdouble);
  108.          break;
  109.       default:
  110.          gl_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type)" );
  111.          return;
  112.    }
  113.    ctx->Array.VertexSize = size;
  114.    ctx->Array.VertexType = type;
  115.    ctx->Array.VertexStride = stride;
  116.    ctx->Array.VertexPtr = (void *) ptr;
  117. }
  118.  
  119.  
  120.  
  121.  
  122. void gl_NormalPointer( GLcontext *ctx,
  123.                        GLenum type, GLsizei stride, const GLvoid *ptr )
  124. {
  125.    if (stride<0) {
  126.       gl_error( ctx, GL_INVALID_VALUE, "glNormalPointer(stride)" );
  127.       return;
  128.    }
  129.    switch (type) {
  130.       case GL_BYTE:
  131.          ctx->Array.NormalStrideB = stride ? stride : 3*sizeof(GLbyte);
  132.          break;
  133.       case GL_SHORT:
  134.          ctx->Array.NormalStrideB = stride ? stride : 3*sizeof(GLshort);
  135.          break;
  136.       case GL_INT:
  137.          ctx->Array.NormalStrideB = stride ? stride : 3*sizeof(GLint);
  138.          break;
  139.       case GL_FLOAT:
  140.          ctx->Array.NormalStrideB = stride ? stride : 3*sizeof(GLfloat);
  141.          break;
  142.       case GL_DOUBLE:
  143.          ctx->Array.NormalStrideB = stride ? stride : 3*sizeof(GLdouble);
  144.          break;
  145.       default:
  146.          gl_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type)" );
  147.          return;
  148.    }
  149.    ctx->Array.NormalType = type;
  150.    ctx->Array.NormalStride = stride;
  151.    ctx->Array.NormalPtr = (void *) ptr;
  152. }
  153.  
  154.  
  155.  
  156. void gl_ColorPointer( GLcontext *ctx,
  157.                       GLint size, GLenum type, GLsizei stride,
  158.                       const GLvoid *ptr )
  159. {
  160.    if (size<3 || size>4) {
  161.       gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(size)" );
  162.       return;
  163.    }
  164.    if (stride<0) {
  165.       gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" );
  166.       return;
  167.    }
  168.    switch (type) {
  169.       case GL_BYTE:
  170.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLbyte);
  171.          break;
  172.       case GL_UNSIGNED_BYTE:
  173.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLubyte);
  174.          break;
  175.       case GL_SHORT:
  176.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLshort);
  177.          break;
  178.       case GL_UNSIGNED_SHORT:
  179.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLushort);
  180.          break;
  181.       case GL_INT:
  182.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLint);
  183.          break;
  184.       case GL_UNSIGNED_INT:
  185.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLuint);
  186.          break;
  187.       case GL_FLOAT:
  188.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLfloat);
  189.          break;
  190.       case GL_DOUBLE:
  191.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLdouble);
  192.          break;
  193.       default:
  194.          gl_error( ctx, GL_INVALID_ENUM, "glColorPointer(type)" );
  195.          return;
  196.    }
  197.    ctx->Array.ColorSize = size;
  198.    ctx->Array.ColorType = type;
  199.    ctx->Array.ColorStride = stride;
  200.    ctx->Array.ColorPtr = (void *) ptr;
  201. }
  202.  
  203.  
  204.  
  205. void gl_IndexPointer( GLcontext *ctx,
  206.                       GLenum type, GLsizei stride, const GLvoid *ptr )
  207. {
  208.    if (stride<0) {
  209.       gl_error( ctx, GL_INVALID_VALUE, "glIndexPointer(stride)" );
  210.       return;
  211.    }
  212.    switch (type) {
  213.       case GL_SHORT:
  214.          ctx->Array.IndexStrideB = stride ? stride : sizeof(GLbyte);
  215.          break;
  216.       case GL_INT:
  217.          ctx->Array.IndexStrideB = stride ? stride : sizeof(GLint);
  218.          break;
  219.       case GL_FLOAT:
  220.          ctx->Array.IndexStrideB = stride ? stride : sizeof(GLfloat);
  221.          break;
  222.       case GL_DOUBLE:
  223.          ctx->Array.IndexStrideB = stride ? stride : sizeof(GLdouble);
  224.          break;
  225.       default:
  226.          gl_error( ctx, GL_INVALID_ENUM, "glIndexPointer(type)" );
  227.          return;
  228.    }
  229.    ctx->Array.IndexType = type;
  230.    ctx->Array.IndexStride = stride;
  231.    ctx->Array.IndexPtr = (void *) ptr;
  232. }
  233.  
  234.  
  235.  
  236. void gl_TexCoordPointer( GLcontext *ctx,
  237.                          GLint size, GLenum type, GLsizei stride,
  238.                          const GLvoid *ptr )
  239. {
  240.    if (size<1 || size>4) {
  241.       gl_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(size)" );
  242.       return;
  243.    }
  244.    switch (type) {
  245.       case GL_SHORT:
  246.          ctx->Array.TexCoordStrideB = stride ? stride : size*sizeof(GLshort);
  247.          break;
  248.       case GL_INT:
  249.          ctx->Array.TexCoordStrideB = stride ? stride : size*sizeof(GLint);
  250.          break;
  251.       case GL_FLOAT:
  252.          ctx->Array.TexCoordStrideB = stride ? stride : size*sizeof(GLfloat);
  253.          break;
  254.       case GL_DOUBLE:
  255.          ctx->Array.TexCoordStrideB = stride ? stride : size*sizeof(GLdouble);
  256.          break;
  257.       default:
  258.          gl_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type)" );
  259.          return;
  260.    }
  261.    if (stride<0) {
  262.       gl_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(stride)" );
  263.       return;
  264.    }
  265.    ctx->Array.TexCoordSize = size;
  266.    ctx->Array.TexCoordType = type;
  267.    ctx->Array.TexCoordStride = stride;
  268.    ctx->Array.TexCoordPtr = (void *) ptr;
  269. }
  270.  
  271.  
  272.  
  273. void gl_EdgeFlagPointer( GLcontext *ctx,
  274.                          GLsizei stride, const GLboolean *ptr )
  275. {
  276.    if (stride<0) {
  277.       gl_error( ctx, GL_INVALID_VALUE, "glEdgeFlagPointer(stride)" );
  278.       return;
  279.    }
  280.    ctx->Array.EdgeFlagStride = stride;
  281.    ctx->Array.EdgeFlagStrideB = stride ? stride : sizeof(GLboolean);
  282.    ctx->Array.EdgeFlagPtr = (GLboolean *) ptr;
  283. }
  284.  
  285.  
  286.  
  287. /*
  288.  * Execute
  289.  */
  290. void gl_ArrayElement( GLcontext *ctx, GLint i )
  291. {
  292.    struct vertex_buffer *VB = ctx->VB;
  293.    GLint count = VB->Count;
  294.  
  295.    /* copy vertex data into the Vertex Buffer */
  296.  
  297.    if (ctx->Array.NormalEnabled) {
  298.       GLbyte *p = (GLbyte*) ctx->Array.NormalPtr
  299.                   + i * ctx->Array.NormalStrideB;
  300.       switch (ctx->Array.NormalType) {
  301.          case GL_BYTE:
  302.             VB->Normal[count][0] = BYTE_TO_FLOAT( p[0] );
  303.             VB->Normal[count][1] = BYTE_TO_FLOAT( p[1] );
  304.             VB->Normal[count][2] = BYTE_TO_FLOAT( p[2] );
  305.             break;
  306.          case GL_SHORT:
  307.             VB->Normal[count][0] = SHORT_TO_FLOAT( ((GLshort*)p)[0] );
  308.             VB->Normal[count][1] = SHORT_TO_FLOAT( ((GLshort*)p)[1] );
  309.             VB->Normal[count][2] = SHORT_TO_FLOAT( ((GLshort*)p)[2] );
  310.             break;
  311.          case GL_INT:
  312.             VB->Normal[count][0] = INT_TO_FLOAT( ((GLint*)p)[0] );
  313.             VB->Normal[count][1] = INT_TO_FLOAT( ((GLint*)p)[1] );
  314.             VB->Normal[count][2] = INT_TO_FLOAT( ((GLint*)p)[2] );
  315.             break;
  316.          case GL_FLOAT:
  317.             VB->Normal[count][0] = ((GLfloat*)p)[0];
  318.             VB->Normal[count][1] = ((GLfloat*)p)[1];
  319.             VB->Normal[count][2] = ((GLfloat*)p)[2];
  320.             break;
  321.          case GL_DOUBLE:
  322.             VB->Normal[count][0] = ((GLdouble*)p)[0];
  323.             VB->Normal[count][1] = ((GLdouble*)p)[1];
  324.             VB->Normal[count][2] = ((GLdouble*)p)[2];
  325.             break;
  326.          default:
  327.             abort();
  328.       }
  329.    }
  330.    else {
  331.       VB->Normal[count][0] = ctx->Current.Normal[0];
  332.       VB->Normal[count][1] = ctx->Current.Normal[0];
  333.       VB->Normal[count][2] = ctx->Current.Normal[0];
  334.    } 
  335.  
  336.    /* TODO: directly set VB->Fcolor instead of calling a glColor command */
  337.    if (ctx->Array.ColorEnabled) {
  338.       GLbyte *p = (GLbyte*) ctx->Array.ColorPtr + i * ctx->Array.ColorStrideB;
  339.       switch (ctx->Array.ColorType) {
  340.          case GL_BYTE:
  341.             switch (ctx->Array.ColorSize) {
  342.                case 4:   glColor4bv( (GLbyte*) p );   break;
  343.                case 3:   glColor3bv( (GLbyte*) p );   break;
  344.             }
  345.             break;
  346.          case GL_UNSIGNED_BYTE:
  347.             switch (ctx->Array.ColorSize) {
  348.                case 3:   glColor3ubv( (GLubyte*) p );   break;
  349.                case 4:   glColor4ubv( (GLubyte*) p );   break;
  350.             }
  351.             break;
  352.          case GL_SHORT:
  353.             switch (ctx->Array.ColorSize) {
  354.                case 3:   glColor3sv( (GLshort*) p );   break;
  355.                case 4:   glColor4sv( (GLshort*) p );   break;
  356.             }
  357.             break;
  358.          case GL_UNSIGNED_SHORT:
  359.             switch (ctx->Array.ColorSize) {
  360.                case 3:   glColor3usv( (GLushort*) p );   break;
  361.                case 4:   glColor4usv( (GLushort*) p );   break;
  362.             }
  363.             break;
  364.          case GL_INT:
  365.             switch (ctx->Array.ColorSize) {
  366.                case 3:   glColor3iv( (GLint*) p );   break;
  367.                case 4:   glColor4iv( (GLint*) p );   break;
  368.             }
  369.             break;
  370.          case GL_UNSIGNED_INT:
  371.             switch (ctx->Array.ColorSize) {
  372.                case 3:   glColor3uiv( (GLuint*) p );   break;
  373.                case 4:   glColor4uiv( (GLuint*) p );   break;
  374.             }
  375.             break;
  376.          case GL_FLOAT:
  377.             switch (ctx->Array.ColorSize) {
  378.                case 3:   glColor3fv( (GLfloat*) p );   break;
  379.                case 4:   glColor4fv( (GLfloat*) p );   break;
  380.             }
  381.             break;
  382.          case GL_DOUBLE:
  383.             switch (ctx->Array.ColorSize) {
  384.                case 3:   glColor3dv( (GLdouble*) p );   break;
  385.                case 4:   glColor4dv( (GLdouble*) p );   break;
  386.             }
  387.             break;
  388.          default:
  389.             abort();
  390.       }
  391.       ctx->VB->MonoColor = GL_FALSE;
  392.    }
  393.    else {
  394.       GLint shift = ctx->ColorShift;
  395.       VB->Fcolor[count][0] = ctx->Current.IntColor[0] << shift;
  396.       VB->Fcolor[count][1] = ctx->Current.IntColor[1] << shift;
  397.       VB->Fcolor[count][2] = ctx->Current.IntColor[2] << shift;
  398.       VB->Fcolor[count][3] = ctx->Current.IntColor[3] << shift;
  399.       if (ctx->Light.ColorMaterialEnabled) {
  400.          GLfloat color[4];
  401.          color[0] = ctx->Current.IntColor[0] * ctx->Visual->InvRedScale;
  402.          color[1] = ctx->Current.IntColor[1] * ctx->Visual->InvGreenScale;
  403.          color[2] = ctx->Current.IntColor[2] * ctx->Visual->InvBlueScale;
  404.          color[3] = ctx->Current.IntColor[3] * ctx->Visual->InvAlphaScale;
  405.          gl_set_material( ctx, ctx->Light.ColorMaterialBitmask, color );
  406.       }
  407.    }
  408.  
  409.    if (ctx->Array.IndexEnabled) {
  410.       GLbyte *p = (GLbyte*) ctx->Array.IndexPtr + i * ctx->Array.IndexStrideB;
  411.       switch (ctx->Array.IndexType) {
  412.          case GL_SHORT:
  413.             VB->Findex[count] = (GLuint) (*((GLshort*) p));
  414.             break;
  415.          case GL_INT:
  416.             VB->Findex[count] = (GLuint) (*((GLint*) p));
  417.             break;
  418.          case GL_FLOAT:
  419.             VB->Findex[count] = (GLuint) (*((GLfloat*) p));
  420.             break;
  421.          case GL_DOUBLE:
  422.             VB->Findex[count] = (GLuint) (*((GLdouble*) p));
  423.             break;
  424.          default:
  425.             abort();
  426.       }
  427.       ctx->VB->MonoColor = GL_FALSE;
  428.    }
  429.    else {
  430.       VB->Findex[count] = ctx->Current.Index;
  431.    }
  432.  
  433.    if (ctx->Array.TexCoordEnabled) {
  434.       GLbyte *p = (GLbyte*) ctx->Array.TexCoordPtr
  435.                   + i * ctx->Array.TexCoordStrideB;
  436.       VB->TexCoord[count][1] = 0.0F;
  437.       VB->TexCoord[count][2] = 0.0F;
  438.       VB->TexCoord[count][3] = 1.0F;
  439.       switch (ctx->Array.TexCoordType) {
  440.          case GL_SHORT:
  441.             switch (ctx->Array.TexCoordSize) {
  442.                /* FALL THROUGH! */
  443.                case 4:   VB->TexCoord[count][3] = ((GLshort*) p)[3];
  444.                case 3:   VB->TexCoord[count][2] = ((GLshort*) p)[2];
  445.                case 2:   VB->TexCoord[count][1] = ((GLshort*) p)[1];
  446.                case 1:   VB->TexCoord[count][0] = ((GLshort*) p)[0];
  447.             }
  448.             break;
  449.          case GL_INT:
  450.             switch (ctx->Array.TexCoordSize) {
  451.                /* FALL THROUGH! */
  452.                case 4:   VB->TexCoord[count][3] = ((GLint*) p)[3];
  453.                case 3:   VB->TexCoord[count][2] = ((GLint*) p)[2];
  454.                case 2:   VB->TexCoord[count][1] = ((GLint*) p)[1];
  455.                case 1:   VB->TexCoord[count][0] = ((GLint*) p)[0];
  456.             }
  457.             break;
  458.          case GL_FLOAT:
  459.             switch (ctx->Array.TexCoordSize) {
  460.                /* FALL THROUGH! */
  461.                case 4:   VB->TexCoord[count][3] = ((GLfloat*) p)[3];
  462.                case 3:   VB->TexCoord[count][2] = ((GLfloat*) p)[2];
  463.                case 2:   VB->TexCoord[count][1] = ((GLfloat*) p)[1];
  464.                case 1:   VB->TexCoord[count][0] = ((GLfloat*) p)[0];
  465.             }
  466.             break;
  467.          case GL_DOUBLE:
  468.             switch (ctx->Array.TexCoordSize) {
  469.                /* FALL THROUGH! */
  470.                case 4:   VB->TexCoord[count][3] = ((GLdouble*) p)[3];
  471.                case 3:   VB->TexCoord[count][2] = ((GLdouble*) p)[2];
  472.                case 2:   VB->TexCoord[count][1] = ((GLdouble*) p)[1];
  473.                case 1:   VB->TexCoord[count][0] = ((GLdouble*) p)[0];
  474.             }
  475.             break;
  476.          default:
  477.             abort();
  478.       }
  479.    }
  480.    else {
  481.       COPY_4V( VB->TexCoord[count], ctx->Current.TexCoord );
  482.    }
  483.  
  484.    if (ctx->Array.EdgeFlagEnabled) {
  485.       GLbyte *b = (GLbyte*) ctx->Array.EdgeFlagPtr
  486.                   + i * ctx->Array.EdgeFlagStrideB;
  487.       VB->Edgeflag[count] = *((GLboolean*) b);
  488.    }
  489.    else {
  490.       VB->Edgeflag[count] = ctx->Current.EdgeFlag;
  491.    }
  492.  
  493.    if (ctx->Array.VertexEnabled) {
  494.       GLbyte *b = (GLbyte*) ctx->Array.VertexPtr
  495.                   + i * ctx->Array.VertexStrideB;
  496.       VB->Obj[count][2] = 0.0F;
  497.       VB->Obj[count][3] = 1.0F;
  498.       switch (ctx->Array.VertexType) {
  499.          case GL_SHORT:
  500.             switch (ctx->Array.VertexSize) {
  501.                /* FALL THROUGH */
  502.                case 4:   VB->Obj[count][3] = ((GLshort*) b)[3];
  503.                case 3:   VB->Obj[count][2] = ((GLshort*) b)[2];
  504.                case 2:   VB->Obj[count][1] = ((GLshort*) b)[1];
  505.                          VB->Obj[count][0] = ((GLshort*) b)[0];
  506.             }
  507.             break;
  508.          case GL_INT:
  509.             switch (ctx->Array.VertexSize) {
  510.                /* FALL THROUGH */
  511.                case 4:   VB->Obj[count][3] = ((GLint*) b)[3];
  512.                case 3:   VB->Obj[count][2] = ((GLint*) b)[2];
  513.                case 2:   VB->Obj[count][1] = ((GLint*) b)[1];
  514.                          VB->Obj[count][0] = ((GLint*) b)[0];
  515.             }
  516.             break;
  517.          case GL_FLOAT:
  518.             switch (ctx->Array.VertexSize) {
  519.                /* FALL THROUGH */
  520.                case 4:   VB->Obj[count][3] = ((GLfloat*) b)[3];
  521.                case 3:   VB->Obj[count][2] = ((GLfloat*) b)[2];
  522.                case 2:   VB->Obj[count][1] = ((GLfloat*) b)[1];
  523.                          VB->Obj[count][0] = ((GLfloat*) b)[0];
  524.             }
  525.             break;
  526.          case GL_DOUBLE:
  527.             switch (ctx->Array.VertexSize) {
  528.                /* FALL THROUGH */
  529.                case 4:   VB->Obj[count][3] = ((GLdouble*) b)[3];
  530.                case 3:   VB->Obj[count][2] = ((GLdouble*) b)[2];
  531.                case 2:   VB->Obj[count][1] = ((GLdouble*) b)[1];
  532.                          VB->Obj[count][0] = ((GLdouble*) b)[0];
  533.             }
  534.             break;
  535.          default:
  536.             abort();
  537.       }
  538.  
  539.       /* Only store vertex if Vertex array pointer is enabled */
  540.       count++;
  541.       VB->Count = count;
  542.       if (count==VB_MAX) {
  543.          gl_transform_vb_part1( ctx, GL_FALSE );
  544.       }
  545.  
  546.    }
  547.    else {
  548.       /* vertex array pointer not enabled: no vertex to process */
  549.    }
  550. }
  551.  
  552.  
  553.  
  554.  
  555. /*
  556.  * Save into display list
  557.  * Use external API entry points since speed isn't too important here
  558.  * and makes the code simpler.  Also, if GL_COMPILE_AND_EXECUTE then
  559.  * execute will happen too.
  560.  */
  561. void gl_save_ArrayElement( GLcontext *ctx, GLint i )
  562. {
  563.    if (ctx->Array.NormalEnabled) {
  564.       GLbyte *p = (GLbyte*) ctx->Array.NormalPtr
  565.                   + i * ctx->Array.NormalStrideB;
  566.       switch (ctx->Array.NormalType) {
  567.          case GL_BYTE:
  568.             glNormal3bv( (GLbyte*) p );
  569.             break;
  570.          case GL_SHORT:
  571.             glNormal3sv( (GLshort*) p );
  572.             break;
  573.          case GL_INT:
  574.             glNormal3iv( (GLint*) p );
  575.             break;
  576.          case GL_FLOAT:
  577.             glNormal3fv( (GLfloat*) p );
  578.             break;
  579.          case GL_DOUBLE:
  580.             glNormal3dv( (GLdouble*) p );
  581.             break;
  582.          default:
  583.             abort();
  584.       }
  585.    }
  586.  
  587.    if (ctx->Array.ColorEnabled) {
  588.       GLbyte *p = (GLbyte*) ctx->Array.ColorPtr + i * ctx->Array.ColorStrideB;
  589.       switch (ctx->Array.ColorType) {
  590.          case GL_BYTE:
  591.             switch (ctx->Array.ColorSize) {
  592.                case 3:   glColor3bv( (GLbyte*) p );   break;
  593.                case 4:   glColor4bv( (GLbyte*) p );   break;
  594.             }
  595.             break;
  596.          case GL_UNSIGNED_BYTE:
  597.             switch (ctx->Array.ColorSize) {
  598.                case 3:   glColor3ubv( (GLubyte*) p );   break;
  599.                case 4:   glColor4ubv( (GLubyte*) p );   break;
  600.             }
  601.             break;
  602.          case GL_SHORT:
  603.             switch (ctx->Array.ColorSize) {
  604.                case 3:   glColor3sv( (GLshort*) p );   break;
  605.                case 4:   glColor4sv( (GLshort*) p );   break;
  606.             }
  607.             break;
  608.          case GL_UNSIGNED_SHORT:
  609.             switch (ctx->Array.ColorSize) {
  610.                case 3:   glColor3usv( (GLushort*) p );   break;
  611.                case 4:   glColor4usv( (GLushort*) p );   break;
  612.             }
  613.             break;
  614.          case GL_INT:
  615.             switch (ctx->Array.ColorSize) {
  616.                case 3:   glColor3iv( (GLint*) p );   break;
  617.                case 4:   glColor4iv( (GLint*) p );   break;
  618.             }
  619.             break;
  620.          case GL_UNSIGNED_INT:
  621.             switch (ctx->Array.ColorSize) {
  622.                case 3:   glColor3uiv( (GLuint*) p );   break;
  623.                case 4:   glColor4uiv( (GLuint*) p );   break;
  624.             }
  625.             break;
  626.          case GL_FLOAT:
  627.             switch (ctx->Array.ColorSize) {
  628.                case 3:   glColor3fv( (GLfloat*) p );   break;
  629.                case 4:   glColor4fv( (GLfloat*) p );   break;
  630.             }
  631.             break;
  632.          case GL_DOUBLE:
  633.             switch (ctx->Array.ColorSize) {
  634.                case 3:   glColor3dv( (GLdouble*) p );   break;
  635.                case 4:   glColor4dv( (GLdouble*) p );   break;
  636.             }
  637.             break;
  638.          default:
  639.             abort();
  640.       }
  641.    }
  642.  
  643.    if (ctx->Array.IndexEnabled) {
  644.       GLbyte *p = (GLbyte*) ctx->Array.IndexPtr + i * ctx->Array.IndexStrideB;
  645.       switch (ctx->Array.IndexType) {
  646.          case GL_SHORT:
  647.             glIndexsv( (GLshort*) p );
  648.             break;
  649.          case GL_INT:
  650.             glIndexiv( (GLint*) p );
  651.             break;
  652.          case GL_FLOAT:
  653.             glIndexfv( (GLfloat*) p );
  654.             break;
  655.          case GL_DOUBLE:
  656.             glIndexdv( (GLdouble*) p );
  657.             break;
  658.          default:
  659.             abort();
  660.       }
  661.    }
  662.  
  663.    if (ctx->Array.TexCoordEnabled) {
  664.       GLbyte *p = (GLbyte*) ctx->Array.TexCoordPtr
  665.                   + i * ctx->Array.TexCoordStrideB;
  666.       switch (ctx->Array.TexCoordType) {
  667.          case GL_SHORT:
  668.             switch (ctx->Array.TexCoordSize) {
  669.                case 1:   glTexCoord1sv( (GLshort*) p );   break;
  670.                case 2:   glTexCoord2sv( (GLshort*) p );   break;
  671.                case 3:   glTexCoord3sv( (GLshort*) p );   break;
  672.                case 4:   glTexCoord4sv( (GLshort*) p );   break;
  673.             }
  674.             break;
  675.          case GL_INT:
  676.             switch (ctx->Array.TexCoordSize) {
  677.                case 1:   glTexCoord1iv( (GLint*) p );   break;
  678.                case 2:   glTexCoord2iv( (GLint*) p );   break;
  679.                case 3:   glTexCoord3iv( (GLint*) p );   break;
  680.                case 4:   glTexCoord4iv( (GLint*) p );   break;
  681.             }
  682.             break;
  683.          case GL_FLOAT:
  684.             switch (ctx->Array.TexCoordSize) {
  685.                case 1:   glTexCoord1fv( (GLfloat*) p );   break;
  686.                case 2:   glTexCoord2fv( (GLfloat*) p );   break;
  687.                case 3:   glTexCoord3fv( (GLfloat*) p );   break;
  688.                case 4:   glTexCoord4fv( (GLfloat*) p );   break;
  689.             }
  690.             break;
  691.          case GL_DOUBLE:
  692.             switch (ctx->Array.TexCoordSize) {
  693.                case 1:   glTexCoord1dv( (GLdouble*) p );   break;
  694.                case 2:   glTexCoord2dv( (GLdouble*) p );   break;
  695.                case 3:   glTexCoord3dv( (GLdouble*) p );   break;
  696.                case 4:   glTexCoord4dv( (GLdouble*) p );   break;
  697.             }
  698.             break;
  699.          default:
  700.             abort();
  701.       }
  702.    }
  703.  
  704.    if (ctx->Array.EdgeFlagEnabled) {
  705.       GLbyte *b = (GLbyte*) ctx->Array.EdgeFlagPtr + i * ctx->Array.EdgeFlagStrideB;
  706.       glEdgeFlagv( (GLboolean*) b );
  707.    }
  708.  
  709.    if (ctx->Array.VertexEnabled) {
  710.       GLbyte *b = (GLbyte*) ctx->Array.VertexPtr
  711.                   + i * ctx->Array.VertexStrideB;
  712.       switch (ctx->Array.VertexType) {
  713.          case GL_SHORT:
  714.             switch (ctx->Array.VertexSize) {
  715.                case 2:   glVertex2sv( (GLshort*) b );   break;
  716.                case 3:   glVertex3sv( (GLshort*) b );   break;
  717.                case 4:   glVertex4sv( (GLshort*) b );   break;
  718.             }
  719.             break;
  720.          case GL_INT:
  721.             switch (ctx->Array.VertexSize) {
  722.                case 2:   glVertex2iv( (GLint*) b );   break;
  723.                case 3:   glVertex3iv( (GLint*) b );   break;
  724.                case 4:   glVertex4iv( (GLint*) b );   break;
  725.             }
  726.             break;
  727.          case GL_FLOAT:
  728.             switch (ctx->Array.VertexSize) {
  729.                case 2:   glVertex2fv( (GLfloat*) b );   break;
  730.                case 3:   glVertex3fv( (GLfloat*) b );   break;
  731.                case 4:   glVertex4fv( (GLfloat*) b );   break;
  732.             }
  733.             break;
  734.          case GL_DOUBLE:
  735.             switch (ctx->Array.VertexSize) {
  736.                case 2:   glVertex2dv( (GLdouble*) b );   break;
  737.                case 3:   glVertex3dv( (GLdouble*) b );   break;
  738.                case 4:   glVertex4dv( (GLdouble*) b );   break;
  739.             }
  740.             break;
  741.          default:
  742.             abort();
  743.       }
  744.    }
  745. }
  746.  
  747.  
  748.  
  749. /*
  750.  * Execute
  751.  */
  752. void gl_DrawArrays( GLcontext *ctx,
  753.                     GLenum mode, GLint first, GLsizei count )
  754. {
  755.    struct vertex_buffer* VB = ctx->VB;
  756.  
  757.    GLint i;
  758.    GLboolean need_edges;
  759.  
  760.    if (INSIDE_BEGIN_END(ctx)) {
  761.       gl_error( ctx, GL_INVALID_OPERATION, "glDrawArrays" );
  762.       return;
  763.    }
  764.    if (count<0) {
  765.       gl_error( ctx, GL_INVALID_VALUE, "glDrawArrays(count)" );
  766.       return;
  767.    }
  768.  
  769.    if (ctx->Primitive==GL_TRIANGLES || ctx->Primitive==GL_QUADS
  770.        || ctx->Primitive==GL_POLYGON) {
  771.       need_edges = GL_TRUE;
  772.    }
  773.    else {
  774.       need_edges = GL_FALSE;
  775.    }
  776.  
  777.    if (!ctx->Light.Enabled
  778.        && !ctx->Texture.Enabled
  779.        && ctx->Array.VertexEnabled && ctx->Array.VertexType==GL_FLOAT
  780.        && ctx->Array.VertexStride==0 && ctx->Array.VertexSize==3
  781.        && !ctx->Array.NormalEnabled
  782.        && !ctx->Array.ColorEnabled
  783.        && !ctx->Array.IndexEnabled
  784.        && !ctx->Array.TexCoordEnabled
  785.        && !ctx->Array.EdgeFlagEnabled) {
  786.       /*
  787.        * SPECIAL CASE:  glVertex3fv() with no lighting
  788.        */
  789.       GLfloat (*vptr)[3];
  790.       GLint remaining;
  791.  
  792.       gl_Begin( ctx, mode );
  793.  
  794.       remaining = count;
  795.       vptr = (GLfloat (*)[3]) ctx->Array.VertexPtr + 3 * first;
  796.       while (remaining>0) {
  797.          GLint vbspace, n;
  798.  
  799.          vbspace = VB_MAX - VB->Start;
  800.          n = MIN2( vbspace, remaining );
  801.  
  802.          gl_xform_points_3fv( n, VB->Eye+VB->Start, ctx->ModelViewMatrix, vptr );
  803.  
  804.          /* assign vertex colors */
  805.          {
  806.             GLint r = ctx->Current.IntColor[0] << ctx->ColorShift;
  807.             GLint g = ctx->Current.IntColor[1] << ctx->ColorShift;
  808.             GLint b = ctx->Current.IntColor[2] << ctx->ColorShift;
  809.             GLint a = ctx->Current.IntColor[3] << ctx->ColorShift;
  810.             GLint i, start = VB->Start;
  811.             for (i=0;i<n;i++) {
  812.                ASSIGN_4V( VB->Fcolor[start+i], r, g, b, a );
  813.             }
  814.          }
  815.  
  816.          /* assign polygon edgeflags */
  817.          if (need_edges) {
  818.             GLint i;
  819.             for (i=0;i<n;i++) {
  820.                VB->Edgeflag[VB->Start+i] = ctx->Current.EdgeFlag;
  821.             }
  822.          }
  823.  
  824.          remaining -= n;
  825.  
  826.          VB->Count = VB->Start + n;
  827.          gl_transform_vb_part2( ctx, remaining==0 ? GL_TRUE : GL_FALSE );
  828.          gl_render_vb( ctx, remaining==0 ? GL_TRUE : GL_FALSE );
  829.  
  830.          vptr += n;
  831.       }
  832.  
  833.       gl_End( ctx );
  834.    }
  835.    else if (!ctx->CompileFlag
  836.        && ctx->Light.Enabled
  837.        && !ctx->Texture.Enabled
  838.        && ctx->Array.VertexEnabled && ctx->Array.VertexType==GL_FLOAT
  839.        && ctx->Array.VertexStride==0 && ctx->Array.VertexSize==4
  840.        && ctx->Array.NormalEnabled && ctx->Array.NormalType==GL_FLOAT
  841.        && ctx->Array.NormalStride==0
  842.        && !ctx->Array.ColorEnabled
  843.        && !ctx->Array.IndexEnabled
  844.        && !ctx->Array.TexCoordEnabled
  845.        && !ctx->Array.EdgeFlagEnabled) {
  846.       /*
  847.        * SPECIAL CASE:  glNormal3fv();  glVertex4fv();  with lighting
  848.        */
  849.       GLfloat (*vptr)[4], (*nptr)[3];
  850.       GLint remaining;
  851.  
  852.       gl_Begin( ctx, mode );
  853.  
  854.       remaining = count;
  855.       vptr = (GLfloat (*)[4]) ctx->Array.VertexPtr + 4 * first;
  856.       nptr = (GLfloat (*)[3]) ctx->Array.NormalPtr + 3 * first;
  857.       while (remaining>0) {
  858.          GLint vbspace, n;
  859.  
  860.          vbspace = VB_MAX - VB->Start;
  861.          n = MIN2( vbspace, remaining );
  862.  
  863.          gl_xform_points_4fv( n, VB->Eye+VB->Start, ctx->ModelViewMatrix, vptr );
  864.          gl_xform_normals_3fv( n, VB->Normal+VB->Start, ctx->ModelViewInv, nptr,
  865.                                ctx->Transform.Normalize );
  866.  
  867.          /* assign polygon edgeflags */
  868.          if (need_edges) {
  869.             GLint i;
  870.             for (i=0;i<n;i++) {
  871.                VB->Edgeflag[VB->Start+i] = ctx->Current.EdgeFlag;
  872.             }
  873.          }
  874.  
  875.          remaining -= n;
  876.  
  877.          VB->Count = VB->Start + n;
  878.          gl_transform_vb_part2( ctx, remaining==0 ? GL_TRUE : GL_FALSE );
  879.          gl_render_vb( ctx, remaining==0 ? GL_TRUE : GL_FALSE );
  880.  
  881.          vptr += n;
  882.          nptr += n;
  883.       }
  884.  
  885.       gl_End( ctx );
  886.    }
  887.    else if (!ctx->CompileFlag
  888.        && ctx->Light.Enabled
  889.        && !ctx->Texture.Enabled
  890.        && ctx->Array.VertexEnabled && ctx->Array.VertexType==GL_FLOAT
  891.        && ctx->Array.VertexStride==0 && ctx->Array.VertexSize==3
  892.        && ctx->Array.NormalEnabled && ctx->Array.NormalType==GL_FLOAT
  893.        && ctx->Array.NormalStride==0
  894.        && !ctx->Array.ColorEnabled
  895.        && !ctx->Array.IndexEnabled
  896.        && !ctx->Array.TexCoordEnabled
  897.        && !ctx->Array.EdgeFlagEnabled) {
  898.       /*
  899.        * SPECIAL CASE:  glNormal3fv();  glVertex3fv();  with lighting
  900.        */
  901.       GLfloat (*vptr)[3], (*nptr)[3];
  902.       GLint remaining;
  903.  
  904.       gl_Begin( ctx, mode );
  905.  
  906.       remaining = count;
  907.       vptr = (GLfloat (*)[3]) ctx->Array.VertexPtr + 3 * first;
  908.       nptr = (GLfloat (*)[3]) ctx->Array.NormalPtr + 3 * first;
  909.       while (remaining>0) {
  910.          GLint vbspace, n;
  911.  
  912.          vbspace = VB_MAX - VB->Start;
  913.          n = MIN2( vbspace, remaining );
  914.  
  915.          gl_xform_points_3fv( n, VB->Eye+VB->Start, ctx->ModelViewMatrix, vptr );
  916.          gl_xform_normals_3fv( n, VB->Normal+VB->Start, ctx->ModelViewInv, nptr,
  917.                                ctx->Transform.Normalize );
  918.  
  919.          /* assign polygon edgeflags */
  920.          if (need_edges) {
  921.             GLint i;
  922.             for (i=0;i<n;i++) {
  923.                VB->Edgeflag[VB->Start+i] = ctx->Current.EdgeFlag;
  924.             }
  925.          }
  926.  
  927.          remaining -= n;
  928.  
  929.          VB->Count = VB->Start + n;
  930.          gl_transform_vb_part2( ctx, remaining==0 ? GL_TRUE : GL_FALSE );
  931.          gl_render_vb( ctx, remaining==0 ? GL_TRUE : GL_FALSE );
  932.  
  933.          vptr += n;
  934.          nptr += n;
  935.       }
  936.  
  937.       gl_End( ctx );
  938.    }
  939.    else {
  940.       /*
  941.        * GENERAL CASE:
  942.        */
  943.       gl_Begin( ctx, mode );
  944.       for (i=0;i<count;i++) {
  945.          gl_ArrayElement( ctx, first+i );
  946.       }
  947.       gl_End( ctx );
  948.    }
  949. }
  950.  
  951.  
  952.  
  953. /*
  954.  * Save into a display list
  955.  */
  956. void gl_save_DrawArrays( GLcontext *ctx,
  957.                          GLenum mode, GLint first, GLsizei count )
  958. {
  959.    GLint i;
  960.  
  961.    if (INSIDE_BEGIN_END(ctx)) {
  962.       gl_error( ctx, GL_INVALID_OPERATION, "glDrawArrays" );
  963.       return;
  964.    }
  965.    if (count<0) {
  966.       gl_error( ctx, GL_INVALID_VALUE, "glDrawArrays(count)" );
  967.       return;
  968.    }
  969.    switch (mode) {
  970.       case GL_POINTS:
  971.       case GL_LINES:
  972.       case GL_LINE_STRIP:
  973.       case GL_LINE_LOOP:
  974.       case GL_TRIANGLES:
  975.       case GL_TRIANGLE_STRIP:
  976.       case GL_TRIANGLE_FAN:
  977.       case GL_QUADS:
  978.       case GL_QUAD_STRIP:
  979.       case GL_POLYGON:
  980.          /* OK */
  981.          break;
  982.       default:
  983.          gl_error( ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" );
  984.          return;
  985.    }
  986.  
  987.  
  988.    /* Note: this will do compile AND execute if needed */
  989.    gl_save_Begin( ctx, mode );
  990.    for (i=0;i<count;i++) {
  991.       gl_save_ArrayElement( ctx, first+i );
  992.    }
  993.    gl_save_End( ctx );
  994. }
  995.  
  996.  
  997.  
  998.  
  999. /*
  1000.  * Execute only
  1001.  */
  1002. void gl_DrawElements( GLcontext *ctx,
  1003.                       GLenum mode, GLsizei count,
  1004.                       GLenum type, const GLvoid *indices )
  1005. {
  1006.    
  1007.    if (INSIDE_BEGIN_END(ctx)) {
  1008.       gl_error( ctx, GL_INVALID_OPERATION, "glDrawElements" );
  1009.       return;
  1010.    }
  1011.    if (count<0) {
  1012.       gl_error( ctx, GL_INVALID_VALUE, "glDrawElements(count)" );
  1013.       return;
  1014.    }
  1015.    switch (mode) {
  1016.       case GL_POINTS:
  1017.       case GL_LINES:
  1018.       case GL_LINE_STRIP:
  1019.       case GL_LINE_LOOP:
  1020.       case GL_TRIANGLES:
  1021.       case GL_TRIANGLE_STRIP:
  1022.       case GL_TRIANGLE_FAN:
  1023.       case GL_QUADS:
  1024.       case GL_QUAD_STRIP:
  1025.       case GL_POLYGON:
  1026.          /* OK */
  1027.          break;
  1028.       default:
  1029.          gl_error( ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" );
  1030.          return;
  1031.    }
  1032.    switch (type) {
  1033.       case GL_UNSIGNED_BYTE:
  1034.          {
  1035.             GLubyte *ub_indices = (GLubyte *) indices;
  1036.             GLint i;
  1037.             gl_Begin( ctx, mode );
  1038.             for (i=0;i<count;i++) {
  1039.                gl_ArrayElement( ctx, (GLint) ub_indices[i] );
  1040.             }
  1041.             gl_End( ctx );
  1042.          }
  1043.          break;
  1044.       case GL_UNSIGNED_SHORT:
  1045.          {
  1046.             GLushort *us_indices = (GLushort *) indices;
  1047.             GLint i;
  1048.             gl_Begin( ctx, mode );
  1049.             for (i=0;i<count;i++) {
  1050.                gl_ArrayElement( ctx, (GLint) us_indices[i] );
  1051.             }
  1052.             gl_End( ctx );
  1053.          }
  1054.          break;
  1055.       case GL_UNSIGNED_INT:
  1056.          {
  1057.             GLuint *ui_indices = (GLuint *) indices;
  1058.             GLint i;
  1059.             gl_Begin( ctx, mode );
  1060.             for (i=0;i<count;i++) {
  1061.                gl_ArrayElement( ctx, (GLint) ui_indices[i] );
  1062.             }
  1063.             gl_End( ctx );
  1064.          }
  1065.          break;
  1066.       default:
  1067.          gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
  1068.          return;
  1069.    }
  1070. }
  1071.  
  1072.  
  1073.  
  1074.  
  1075. /*
  1076.  * Save (and perhaps execute)
  1077.  */
  1078. void gl_save_DrawElements( GLcontext *ctx,
  1079.                            GLenum mode, GLsizei count,
  1080.                            GLenum type, const GLvoid *indices )
  1081. {
  1082.    switch (type) {
  1083.       case GL_UNSIGNED_BYTE:
  1084.          {
  1085.             GLubyte *ub_indices = (GLubyte *) indices;
  1086.             GLint i;
  1087.             gl_save_Begin( ctx, mode );
  1088.             for (i=0;i<count;i++) {
  1089.                gl_save_ArrayElement( ctx, (GLint) ub_indices[i] );
  1090.             }
  1091.             gl_save_End( ctx );
  1092.          }
  1093.          break;
  1094.       case GL_UNSIGNED_SHORT:
  1095.          {
  1096.             GLushort *us_indices = (GLushort *) indices;
  1097.             GLint i;
  1098.             gl_save_Begin( ctx, mode );
  1099.             for (i=0;i<count;i++) {
  1100.                gl_save_ArrayElement( ctx, (GLint) us_indices[i] );
  1101.             }
  1102.             gl_save_End( ctx );
  1103.          }
  1104.          break;
  1105.       case GL_UNSIGNED_INT:
  1106.          {
  1107.             GLuint *ui_indices = (GLuint *) indices;
  1108.             GLint i;
  1109.             gl_save_Begin( ctx, mode );
  1110.             for (i=0;i<count;i++) {
  1111.                gl_save_ArrayElement( ctx, (GLint) ui_indices[i] );
  1112.             }
  1113.             gl_save_End( ctx );
  1114.          }
  1115.          break;
  1116.       default:
  1117.          gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
  1118.          return;
  1119.    }
  1120. }
  1121.  
  1122.  
  1123.  
  1124.  
  1125. void gl_InterleavedArrays( GLcontext *ctx,
  1126.                            GLenum format, GLsizei stride,
  1127.                            const GLvoid *pointer )
  1128. {
  1129.    GLboolean tflag, cflag, nflag;  /* enable/disable flags */
  1130.    GLint tcomps, ccomps, vcomps;   /* components per texcoord, color, vertex */
  1131.    GLenum ctype;                   /* color type */
  1132.    GLint coffset, noffset, voffset;/* color, normal, vertex offsets */
  1133.    GLint defstride;                /* default stride */
  1134.    GLint c, f;
  1135.  
  1136.    f = sizeof(GLfloat);
  1137.    c = f * ((4*sizeof(GLubyte) + (f-1)) / f);
  1138.  
  1139.    if (stride<0) {
  1140.       gl_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
  1141.       return;
  1142.    }
  1143.  
  1144.    switch (format) {
  1145.       case GL_V2F:
  1146.          tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_FALSE;
  1147.          tcomps = 0;  ccomps = 0;  vcomps = 2;
  1148.          voffset = 0;
  1149.          defstride = 2*f;
  1150.          break;
  1151.       case GL_V3F:
  1152.          tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_FALSE;
  1153.          tcomps = 0;  ccomps = 0;  vcomps = 3;
  1154.          voffset = 0;
  1155.          defstride = 3*f;
  1156.          break;
  1157.       case GL_C4UB_V2F:
  1158.          tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
  1159.          tcomps = 0;  ccomps = 4;  vcomps = 2;
  1160.          ctype = GL_UNSIGNED_BYTE;
  1161.          coffset = 0;
  1162.          voffset = c;
  1163.          defstride = c + 2*f;
  1164.          break;
  1165.       case GL_C4UB_V3F:
  1166.          tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
  1167.          tcomps = 0;  ccomps = 4;  vcomps = 3;
  1168.          ctype = GL_UNSIGNED_BYTE;
  1169.          coffset = 0;
  1170.          voffset = c;
  1171.          defstride = c + 3*f;
  1172.          break;
  1173.       case GL_C3F_V3F:
  1174.          tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
  1175.          tcomps = 0;  ccomps = 3;  vcomps = 3;
  1176.          ctype = GL_FLOAT;
  1177.          coffset = 0;
  1178.          voffset = 3*f;
  1179.          defstride = 6*f;
  1180.          break;
  1181.       case GL_N3F_V3F:
  1182.          tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_TRUE;
  1183.          tcomps = 0;  ccomps = 0;  vcomps = 3;
  1184.          noffset = 0;
  1185.          voffset = 3*f;
  1186.          defstride = 6*f;
  1187.          break;
  1188.       case GL_C4F_N3F_V3F:
  1189.          tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_TRUE;
  1190.          tcomps = 0;  ccomps = 4;  vcomps = 3;
  1191.          ctype = GL_FLOAT;
  1192.          coffset = 0;
  1193.          noffset = 4*f;
  1194.          voffset = 7*f;
  1195.          defstride = 10*f;
  1196.          break;
  1197.       case GL_T2F_V3F:
  1198.          tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_FALSE;
  1199.          tcomps = 2;  ccomps = 0;  vcomps = 3;
  1200.          voffset = 2*f;
  1201.          defstride = 5*f;
  1202.          break;
  1203.       case GL_T4F_V4F:
  1204.          tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_FALSE;
  1205.          tcomps = 4;  ccomps = 0;  vcomps = 4;
  1206.          voffset = 4*f;
  1207.          defstride = 8*f;
  1208.          break;
  1209.       case GL_T2F_C4UB_V3F:
  1210.          tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_FALSE;
  1211.          tcomps = 2;  ccomps = 4;  vcomps = 3;
  1212.          ctype = GL_UNSIGNED_BYTE;
  1213.          coffset = 2*f;
  1214.          voffset = c+2*f;
  1215.          defstride = c+5*f;
  1216.          break;
  1217.       case GL_T2F_C3F_V3F:
  1218.          tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_FALSE;
  1219.          tcomps = 2;  ccomps = 3;  vcomps = 3;
  1220.          ctype = GL_FLOAT;
  1221.          coffset = 2*f;
  1222.          voffset = 5*f;
  1223.          defstride = 8*f;
  1224.          break;
  1225.       case GL_T2F_N3F_V3F:
  1226.          tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_TRUE;
  1227.          tcomps = 2;  ccomps = 0;  vcomps = 3;
  1228.          noffset = 2*f;
  1229.          voffset = 5*f;
  1230.          defstride = 8*f;
  1231.          break;
  1232.       case GL_T2F_C4F_N3F_V3F:
  1233.          tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_TRUE;
  1234.          tcomps = 2;  ccomps = 4;  vcomps = 3;
  1235.          ctype = GL_FLOAT;
  1236.          coffset = 2*f;
  1237.          noffset = 6*f;
  1238.          voffset = 9*f;
  1239.          defstride = 12*f;
  1240.          break;
  1241.       case GL_T4F_C4F_N3F_V4F:
  1242.          tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_TRUE;
  1243.          tcomps = 4;  ccomps = 4;  vcomps = 4;
  1244.          ctype = GL_FLOAT;
  1245.          coffset = 4*f;
  1246.          noffset = 8*f;
  1247.          voffset = 11*f;
  1248.          defstride = 15*f;
  1249.          break;
  1250.       default:
  1251.          gl_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
  1252.          return;
  1253.    }
  1254.  
  1255.    if (stride==0) {
  1256.       stride = defstride;
  1257.    }
  1258.  
  1259.    gl_DisableClientState( ctx, GL_EDGE_FLAG_ARRAY );
  1260.    gl_DisableClientState( ctx, GL_INDEX_ARRAY );
  1261.  
  1262.    if (tflag) {
  1263.       gl_EnableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
  1264.       gl_TexCoordPointer( ctx, tcomps, GL_FLOAT, stride, pointer );
  1265.    }
  1266.    else {
  1267.       gl_DisableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
  1268.    }
  1269.  
  1270.    if (cflag) {
  1271.       gl_EnableClientState( ctx, GL_COLOR_ARRAY );
  1272.       gl_ColorPointer( ctx, ccomps, ctype, stride,
  1273.                        (GLubyte*) pointer + coffset );
  1274.    }
  1275.    else {
  1276.       gl_DisableClientState( ctx, GL_COLOR_ARRAY );
  1277.    }
  1278.  
  1279.    if (nflag) {
  1280.       gl_EnableClientState( ctx, GL_NORMAL_ARRAY );
  1281.       gl_NormalPointer( ctx, GL_FLOAT, stride,
  1282.                         (GLubyte*) pointer + noffset );
  1283.    }
  1284.    else {
  1285.       gl_DisableClientState( ctx, GL_NORMAL_ARRAY );
  1286.    }
  1287.  
  1288.    gl_EnableClientState( ctx, GL_VERTEX_ARRAY );
  1289.    gl_VertexPointer( ctx, vcomps, GL_FLOAT, stride,
  1290.                      (GLubyte *) pointer + voffset );
  1291. }
  1292.  
  1293.  
  1294.  
  1295. void gl_save_InterleavedArrays( GLcontext *ctx,
  1296.                                 GLenum format, GLsizei stride,
  1297.                                 const GLvoid *pointer )
  1298. {
  1299.    /* Just execute since client-side state changes aren't put in
  1300.     * display lists.
  1301.     */
  1302.    gl_InterleavedArrays( ctx, format, stride, pointer );
  1303. }
  1304.  
  1305.